﻿//
#include <osgViewer/viewer>
#include <osgEarth/Notify>
#include <osgEarth/EarthManipulator>
#include <osgEarth/MapNode>
#include <osgEarth/Threading>
#include <osgEarth/ShaderGenerator>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgUtil/Optimizer>
#include <iostream>
#include <osgEarth/Metrics>
#include "osgEarth/GDAL";
using namespace osgEarth;
using namespace osgEarth::Util;
#include <iostream>
#include <string>
using namespace std;

int main()
{
	osgEarth::initialize();
	//create a viewer
	osgViewer::Viewer viewer;
	viewer.setUpViewInWindow(0, 100, 800, 600);
	viewer.setReleaseContextAtEndOfFrameHint(false);
	//set camera manipulator
	viewer.setCameraManipulator(new EarthManipulator);
	osgEarth::Map* map = new osgEarth::Map();

	//layer
	//GDALImageLayer* layer1 = new GDALImageLayer();
	//layer1->setURL(osgEarth::URI("E:/coding/osgearth2023/osgearth3.4/data/world.tif"));
	//map->addLayer(layer1);

	//NDVI
	GDALImageLayer::Options ndviOpts;
	//这里如果要使用自己的Shader对GDAL数据进行配色，需要设置coverage=true。
	//否则会按照默认RGB 8bit绘制，对于但波段会按 Grey 8bit绘制。
	ndviOpts.coverage() = true;
	GDALImageLayer* ndviLayer = new GDALImageLayer(ndviOpts);
	ndviLayer->setURL(osgEarth::URI("ndvi_cog.tif"));
	map->addLayer(ndviLayer);
	{//NDVI shader
		VirtualProgram* vp1 = new VirtualProgram;//每个图层只能设置一个VirtualProgram
		vp1->setName("ndvi");
		string source_fs1 = R"(
			void ndvi_color(inout vec4 color){
				if( color.r<-800.0 )  color.rgb=vec3(0.78, 0.73, 0.66);
				else if( color.r<1000.0 )  color.rgb=vec3(0.69 , 0.58 , 0.41 );
				else if( color.r<2000.0 )  color.rgb=vec3(0.57 , 0.44 , 0.24 );
				else if( color.r<3000.0 )  color.rgb=vec3(0.58 , 0.71 , 0.07 );
				else if( color.r<4000.0 )  color.rgb=vec3(0.40 , 0.63 , 0.00 );
				else if( color.r<6000.0 )  color.rgb=vec3(0.23 , 0.52 , 0.00 );
				else if( color.r<8000.0 )  color.rgb=vec3(0.00 , 0.37 , 0.00 );
				else if( color.r<10001.0)  color.rgb=vec3(0.00 , 0.21 , 0.00 );	
				else color.rgba=vec4(0.0,0.2,0.5,1.0);//some other values include nodata.
			}
		)";
		vp1->setFunction("ndvi_color", source_fs1, VirtualProgram::LOCATION_FRAGMENT_COLORING, 1);
		ndviLayer->getOrCreateStateSet()->setAttributeAndModes(vp1, osg::StateAttribute::ON);
	}

	//{//virtual program
	//	string source_vs1 = R"(
	//		void myfunc_vertexmodel(inout vec4 vertex){
	//		}
	//	)";
	//	string source_vs2 = R"(
	//		void myfunc_vertexclip(inout vec4 vertex){
	//		}
	//	)";
	//	//如果设置了LOCATION_VERTEX_TRANSFORM_MODEL_TO_VIEW函数，那么osgEarth默认的Model2View代码就会消失。
	//	string source_vs3 = R"(
	//		void myfunc_vertextranform_m2v(){
	//		}
	//	)";
	//	string source_vs4 = R"(
	//		void myfunc_vertexview(inout vec4 vertex){
	//		}
	//	)";
	//	string source_vs5 = R"(
	//		void myfunc_vs_undefined1(inout vec4 vertex){
	//		}
	//	)";
	//	string source_vs6 = R"(
	//		void myfunc_vs_undefined2(inout vec4 vertex){
	//		}
	//	)";
	//	string source_fs1 = R"(
	//		void myfunc_fragmentcoloring(inout vec4 color){
	//		}
	//	)";
	//	string source_fs2 = R"(
	//		void myfunc_fragmentlighting(inout vec4 color){
	//		}
	//	)";
	//	string source_fs3 = R"(
	//		void myfunc_fragmentoutput(inout vec4 color){
	//		}
	//	)";

	//	/*
	//	* 每个shader是分别编译的，编译的代码在
	//	void Program::compileGLObjects( osg::State& state )
	//	这个函数里看 _shaderList[i]->compileShader( state );
	//	每个独立的shader代码片段都单独的在 _shaderList[i] 里面，最后的一个shader是main函数的代码片段。
	//	单独编译每个shader代码片段的时候需要声明用到的外部变量否则不能通过编译阶段。
	//	前面个代码片段编译都通过后才到program的 link阶段。
	//	*/

	//	VirtualProgram* vp1 = new VirtualProgram;//每个图层只能设置一个VirtualProgram
	//	vp1->setName("my");
	//	//Shader文件的基本规则和c语言差不多。
	//	//Shader的应用分为两个阶段，
	//	//第一个阶段是编译阶段，编译阶段每部分代码片段包含自身的实现代码，如果需要引用其他代码需要在顶部声明。
	//	//第二个阶段是链接阶段，链接阶段会组装多个代码片段，不能有重复的函数实现（也就是函数名称不能相同），声明的代码必须有实现的代码部分。
	//	//
	//	// LOCATION_UNDEFINED 这个位置并不能插入代码，用了这个位置程序报错。
	//	vp1->setFunction("myfunc_vertexmodel", source_vs1, VirtualProgram::LOCATION_VERTEX_MODEL, 1 );
	//	vp1->setFunction("myfunc_vertexclip", source_vs2, VirtualProgram::LOCATION_VERTEX_CLIP, 2);
	//	//这个函数不带参数，即使开发这自己声明了参数，在编译阶段也会变为一个没有参数的函数
	//	//vp1->setFunction("myfunc_vertextranform_m2v", source_vs3, VirtualProgram::LOCATION_VERTEX_TRANSFORM_MODEL_TO_VIEW, 3);
	//	vp1->setFunction("myfunc_vertexview", source_vs4, VirtualProgram::LOCATION_VERTEX_VIEW, 4);

	//	vp1->setFunction("myfunc_fragmentcoloring", source_fs1, VirtualProgram::LOCATION_FRAGMENT_COLORING, 1);
	//	vp1->setFunction("myfunc_fragmentlighting", source_fs2, VirtualProgram::LOCATION_FRAGMENT_LIGHTING, 2);
	//	//vp1->setFunction("myfunc_fragmentoutput", source_fs3, VirtualProgram::LOCATION_FRAGMENT_OUTPUT, 3);

	//	layer1->getOrCreateStateSet()->setAttributeAndModes(vp1, osg::StateAttribute::ON);

	//	//disable default applyElevation shader codes. 使用自己的高程计算代码，关闭默认高程代码
	//	//layer1->getOrCreateStateSet()->setDefine("OE_TERRAIN_RENDER_ELEVATION", osg::StateAttribute::OFF);

	//	// 一个图层只能设置一个VirtualProgram
	//	//VirtualProgram* vp2 = new VirtualProgram;
	//	//vp2->setName("name_vp2");
	//	//vp2->setFunction("myfunc_undefined2", source1, VirtualProgram::LOCATION_VERTEX_MODEL, 2);
	//	//layer1->getOrCreateStateSet()->setAttributeAndModes(vp2);// 这个设置后vp1就不生效了

	//}

	osg::ref_ptr<osgEarth::MapNode> mapNode = new osgEarth::MapNode(map);
	viewer.setSceneData(mapNode);
	return Metrics::run(viewer);
}